﻿using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Text;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Xml;

namespace Hxsoft
{
	public class CustomXsltContext : XsltContext
	{
		// XsltArgumentList to store my user defined variables
		private XsltArgumentList m_ArgList;
		// Constructors 
		public CustomXsltContext()
		{ }
		public CustomXsltContext(NameTable nt)
			: base(nt)
		{
		}
		public CustomXsltContext(NameTable nt, XsltArgumentList argList)
			: base(nt)
		{
			m_ArgList = argList;
		}
		// Returns the XsltArgumentList that contains custom variable definitions.
		public XsltArgumentList ArgList
		{
			get
			{
				return m_ArgList;
			}
		}

		// Function to resolve references to my custom functions.
		public override IXsltContextFunction ResolveFunction(string prefix,
	 string name, XPathResultType[] ArgTypes)
		{
			XPathRegExExtensionFunction func = null;
			// Create an instance of appropriate extension function class.
			switch (name)
			{
				case "Match":
					// Usage 
					// myFunctions:Matches(string source, string Regex_pattern) returns Boolean
					func = new XPathRegExExtensionFunction("Match", 2, 2, new
		XPathResultType[] { XPathResultType.String, XPathResultType.String }
		, XPathResultType.Boolean);
					break;
				case "Split":
					// Usage 
					// myFunctions:Split(string source, string Regex_pattern, int n) returns string
					func = new XPathRegExExtensionFunction("Split", 3, 3, new
		XPathResultType[] {XPathResultType.String, XPathResultType.String, 
XPathResultType.Number}, XPathResultType.String);
					break;
				case "Replace":
					// Usage
					// myFunctions:Replace(string source, string Regex_pattern, string replacement_string) returns string
					func = new XPathRegExExtensionFunction("Replace", 3, 3, new
		XPathResultType[] {XPathResultType.String, XPathResultType.String, 
XPathResultType.String}, XPathResultType.String);
					break;
			}
			return func;
		}
		// Function to resolve references to my custom variables.
		public override IXsltContextVariable ResolveVariable(string prefix, string name)
		{
			// Create an instance of an XPathExtensionVariable.
			XPathExtensionVariable Var;
			Var = new XPathExtensionVariable(name);
			return Var;
		}
		public override int CompareDocument(string baseUri, string nextbaseUri)
		{
			return 0;
		}
		public override bool PreserveWhitespace(XPathNavigator node)
		{
			return true;
		}
		public override bool Whitespace
		{
			get
			{
				return true;
			}
		}
	}




	public class XPathRegExExtensionFunction : IXsltContextFunction
	{
		private XPathResultType[] m_ArgTypes;
		private XPathResultType m_ReturnType;
		private string m_FunctionName;
		private int m_MinArgs;
		private int m_MaxArgs;
		// Methods to access the private fields.
		public int Minargs
		{
			get
			{
				return m_MinArgs;
			}
		}
		public int Maxargs
		{
			get
			{
				return m_MaxArgs;
			}
		}
		public XPathResultType[] ArgTypes
		{
			get
			{
				return m_ArgTypes;
			}
		}
		public XPathResultType ReturnType
		{
			get
			{
				return m_ReturnType;
			}
		}
		// Constructor
		public XPathRegExExtensionFunction(string name, int minArgs, int
	 maxArgs, XPathResultType[] argTypes, XPathResultType returnType)
		{
			m_FunctionName = name;
			m_MinArgs = minArgs;
			m_MaxArgs = maxArgs;
			m_ArgTypes = argTypes;
			m_ReturnType = returnType;
		}
		// This method is invoked at run time to execute the user defined function.
		public object Invoke(XsltContext xsltContext, object[] args,
	 XPathNavigator docContext)
		{
			Regex r;
			string str = null;
			// The two custom XPath extension functions
			switch (m_FunctionName)
			{
				case "Match":
					r = new Regex(args[1].ToString());
					MatchCollection m = r.Matches(args[0].ToString());
					if (m.Count == 0)
					{
						return false;
					}
					else
					{
						return true;
					}
					break;

				case "Split":
					r = new Regex(args[1].ToString());
					string[] s1 = r.Split(args[0].ToString());
					int n = Convert.ToInt32(args[2]);
					if (s1.Length < n)
						str = "";
					else
						str = s1[n - 1];
					break;
				case "Replace":
					r = new Regex(args[1].ToString());
					string s2 = r.Replace(args[0].ToString(), args[2].ToString());
					str = s2;
					break;
			}
			return (object)str;
		}
	}




	public class XPathExtensionVariable : IXsltContextVariable
	{
		// The name of the user-defined variable to resolve
		private string m_VarName;
		public XPathExtensionVariable(string VarName)
		{
			m_VarName = VarName;
		}
		// This method is invoked at run time to find the value of the user defined variable.
		public object Evaluate(XsltContext xsltContext)
		{
			XsltArgumentList vars = ((CustomXsltContext)xsltContext).ArgList;
			return vars.GetParam(m_VarName, null);
		}
		public bool IsLocal
		{
			get
			{
				return false;
			}
		}
		public bool IsParam
		{
			get
			{
				return false;
			}
		}
		public XPathResultType VariableType
		{
			get
			{
				return XPathResultType.Any;
			}
		}
	}
}
